/**
 *
 */
package br.gov.ms.tce.cjur.service.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Named;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRPdfExporter;

import org.springframework.transaction.annotation.Transactional;

import br.gov.ms.tce.bean.cjur.Solicitacao;
import br.gov.ms.tce.bean.cjur.SolicitacaoItem;
import br.gov.ms.tce.bean.cjur.SolicitacaoItemResponsavel;
import br.gov.ms.tce.bean.comum.Comparavel;
import br.gov.ms.tce.bean.comum.Pessoa;
import br.gov.ms.tce.bean.comum.PessoaFisica;
import br.gov.ms.tce.bean.comum.Responsavel;
import br.gov.ms.tce.bean.comum.TipoClassificacao;
import br.gov.ms.tce.cjur.factory.SolicitacaoItemFactory;
import br.gov.ms.tce.cjur.helper.CjurHelper;
import br.gov.ms.tce.cjur.helper.CjurHelper.PeriodoFiltro;
import br.gov.ms.tce.cjur.relatorio.SolicitacaoReport;
import br.gov.ms.tce.cjur.service.SolicitacaoService;
import br.gov.ms.tce.modelo.dao.SolicitacaoDAO;

/**
 * @author Anderson Paulino
 * @date 25/07/2011
 */
@Named
public class SolicitacaoServiceImpl extends AbstractService implements SolicitacaoService {

	@Inject
	private SolicitacaoDAO solicitacaoDAO;

	/**
	 * @see br.gov.ms.tce.cjur.service.SolicitacaoService#salvar(br.gov.ms.tce.bean.cjur.Solicitacao)
	 */
	@Override
	public void salvar(Solicitacao solicitacao) {
		solicitacaoDAO.persist(solicitacao);
	}


	/**
	 * @see br.gov.ms.tce.cjur.service.SolicitacaoService#salvar(br.gov.ms.tce.bean.comum.Pessoa, br.gov.ms.tce.bean.comum.Pessoa)
	 */
	@Override
	@Transactional
	public Solicitacao salvar(Pessoa po, Pessoa pa) {
		List<SolicitacaoItem> itens = new ArrayList<SolicitacaoItem>();
		
		if (!((Comparavel) po).igual(pa)) {
			TipoClassificacao tc = pa.getCod()!=null?TipoClassificacao.TIPO_SOLICITACAO_ITEM_ATUALIZAR:TipoClassificacao.TIPO_SOLICITACAO_ITEM_ATUALIZAR; 
			itens.add(SolicitacaoItemFactory.create((Comparavel) pa,tc));
		}
		
		
		if(po instanceof PessoaFisica)
			itens.addAll(criaListaSI(new ArrayList<Comparavel>(po.getDocumentoPessoals()),
				new ArrayList<Comparavel>(pa.getDocumentoPessoals())));
		
		itens.addAll(criaListaSI(new ArrayList<Comparavel>(po.getEmails()),
				new ArrayList<Comparavel>(pa.getEmails())));
		itens.addAll(criaListaSI(new ArrayList<Comparavel>(po.getEnderecos()),
				new ArrayList<Comparavel>(pa.getEnderecos())));
		itens.addAll(criaListaSI(new ArrayList<Comparavel>(po.getTelefones()),
				new ArrayList<Comparavel>(pa.getTelefones())));
		
		
		
		itens.addAll(criaListaSIResponsavel(pa));
		return salvar(po, itens);
	}

	/**
	 * @param po
	 * @param itens
	 */
	private Solicitacao salvar(Pessoa po, List<SolicitacaoItem> itens) {
		Pessoa pessoa = po.getCod()!=null?po:null;
		Solicitacao solicitacao = new Solicitacao(pessoa, itens);		
		solicitacao.setPessoaSolicitante(getPessoaFisicaAutenticado());
		solicitacaoDAO.persist(solicitacao);
		return solicitacao;

	}

	/**
	 * @param responsavels
	 * @param responsavels2
	 * @return
	 */
	private List<SolicitacaoItemResponsavel> criaListaSIResponsavel(Pessoa pa) {
		List<SolicitacaoItemResponsavel> sis = new ArrayList<SolicitacaoItemResponsavel>();
		
		if(pa instanceof PessoaFisica){
			for (Responsavel resp : ((PessoaFisica)pa).getResponsavels()) {
				if (resp.getCod() == null) {
					SolicitacaoItemResponsavel sir = new SolicitacaoItemResponsavel(resp);
					sir.setTipo(TipoClassificacao.TIPO_SOLICITACAO_ITEM_INSERIR);
					sis.add(sir);
				}
			}
		}
		return sis;
	}

	/**
	 * @param pessoaOriginal
	 * @param pessoaAlterada
	 * @param itens
	 */
	private List<SolicitacaoItem> criaListaSI(List<Comparavel> listOriginal,
			List<Comparavel> listAlterada) {
		List<SolicitacaoItem> itens = new ArrayList<SolicitacaoItem>();
		for (Comparavel compa : listAlterada) {
			if (compa.getCod() != null) {
				for (Comparavel compo : listOriginal) {
					if (compa.getTipo().equals(compo.getTipo())) {
						if (!compa.igual(compo)) {
							itens.add(SolicitacaoItemFactory.create(compa,
									TipoClassificacao.TIPO_SOLICITACAO_ITEM_ATUALIZAR));
						}
					}
				}
			} else {
				itens.add(SolicitacaoItemFactory.create(compa,
						TipoClassificacao.TIPO_SOLICITACAO_ITEM_INSERIR));
			}
		}
		return itens;
	}

	/**
	 * @see br.gov.ms.tce.cjur.service.SolicitacaoService#gerarFichaSolicitacao(br.gov.ms.tce.bean.cjur.Solicitacao)
	 */
	@Override
	public InputStream gerarFichaSolicitacao(Solicitacao solicitacao) {

		InputStream rel = null;
		
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		
		List<SolicitacaoReport> srs = new ArrayList<SolicitacaoReport>();
		for (SolicitacaoItem si : solicitacao.getSolicitacaoItems()) {
			srs.add(new SolicitacaoReport(si));
		}
		
		JRDataSource jrds = new JRBeanCollectionDataSource(srs);
		String fileName = "/solicitacao_detalhe.jasper";
		String outFileName = "ficha_solicitacao_"+ solicitacao.getCod()+".pdf";
		HashMap<String,Object> hm = new HashMap<String,Object>();
		hm.put("solicitacaoCod", solicitacao.getCod().toString());
		hm.put("nome", CjurHelper.getNomePessoaAlterada(solicitacao));
		hm.put("data", solicitacao.getDataSolicitacao());

		try {
			JasperPrint print = JasperFillManager.fillReport(this.getClass().getResourceAsStream(fileName), hm, jrds);
			JRExporter exporter = new JRPdfExporter();
			exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, outFileName);
			exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, baos);
			exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
			exporter.exportReport();
			rel = new ByteArrayInputStream(baos.toByteArray());

		} catch (JRException e) {
			e.printStackTrace();

		} catch (Exception e) {
			e.printStackTrace();

		}
		return rel;
	}

	/**
	 * @see br.gov.ms.tce.cjur.service.SolicitacaoService#findByUsuarioAutenticadoAndPeriodoAndSituacao(java.lang.Integer, br.gov.ms.tce.bean.comum.TipoClassificacao)
	 */
	@Override
	public List<Solicitacao> findByUsuarioAutenticadoAndPeriodoAndSituacao(PeriodoFiltro periodoFiltro,	TipoClassificacao situacao) {		
		
		Date[] datas = CjurHelper.criaDatasPeloPeriodo(periodoFiltro);
		
		return solicitacaoDAO.findByPessoSolicitanteAndPeriodoAndSituacao(getPessoaFisicaAutenticado(), datas[0], datas[1], situacao);
	}
}
